<?php
/**
 * Request Contract
 */

namespace dragon\Contract;

use dragon\Exceptions\RequestException;
use dragon\Request\Base\HttpRequest;
use dragon\Request\Base\SoapRequest;
use dragon\Support\Dictionary;

abstract class Request
{
    protected $method, $url, $apiMethodName, $params, $get, $post, $response, $statusCode, $message;
    protected $fieldMapping = [];   // 字段映射
    protected $fieldDict = [];   // 字段字典转化

    // auto run request
    public function run($options = []) {
        if($this->method == 'soap') {
            return $this->soapRun($options);
        } else {
            return $this->httpRun($options);
        }
    }

    // web service request
    public function soapRun($options = []) {
        $httpClient = new SoapRequest();
        $httpClient->run($this, $options);
        return $this;
    }

    // http request
    public function httpRun($options = []) {
        $httpClient = new HttpRequest();
        $httpClient->run($this, $options);
        return $this;
    }

    /**
     * field mapping
     * @param $data
     * @param int $dimension    // 数组维度
     * @return mixed
     */
    protected function fieldMapping($data, $dimension = 1) {
        if(!$this->fieldMapping || !$data) return $data;

        $_data = [];
        foreach($data as $key => $val) {
            if($dimension == 1 && isset($this->fieldMapping[$key])) {
                $_data[$this->fieldMapping[$key]] = $val;
            } elseif ($dimension == 2 && is_array($val)) {
                $_data[$key] = $this->fieldMapping($val);
            }
        }
        return $_data;
    }

    /**
     * field Dictionary Convert
     * @param $data
     * @param int $dimension    // 数组维度
     * @return mixed
     */
    protected function fieldDictConvert($data, $dimension = 1) {
        if(!$this->fieldDict || !$data) return $data;

        $_data = [];
        foreach($data as $key => $val) {
            if($dimension == 1 && isset($this->fieldDict[$key])) {
                if($this->fieldDict[$key] == 'datetime') {
                    $_data[$key] = $val ? date('Y-m-d H:i:s', $val) : '';
                } else {
                    $_data[$key] = Dictionary::get($this->fieldDict[$key], $val);
                }
            } elseif ($dimension == 1) {
                $_data[$key] = $val;
            } elseif ($dimension == 2 && is_array($val)) {
                $_data[$key] = $this->fieldDictConvert($val);
            }
        }
        return $_data;
    }

    /**
     * @return mixed
     */
    public function getUrl()
    {
        return $this->url;
    }

    /**
     * @param mixed $url
     */
    public function setUrl($url)
    {
        $this->url = $url;
    }

    /**
     * @param $params
     * @param int $dimension  数组维度
     * @return mixed
     */
    protected function requestTransfer($params, $dimension = 1) {
        if(is_object($params)) $params = $params->toArray();
        $params = $this->fieldMapping($params, $dimension);
        return $this->fieldDictConvert($params, $dimension);
    }

    /**
     * @return mixed
     */
    public function getParams()
    {
        return $this->requestTransfer($this->params);
    }

    /**
     * @param mixed $params
     */
    public function setParams($params)
    {
        $this->params = $params;
    }

    /**
     * @return mixed
     */
    public function getGet()
    {
        return $this->get;
    }

    /**
     * @param mixed $get
     */
    public function setGet($get)
    {
        $this->get = $get;
    }

    /**
     * @return mixed
     */
    public function getPost()
    {
        return $this->requestTransfer($this->post);
    }

    /**
     * @param mixed $post
     */
    public function setPost($post)
    {
        $this->post = $post;
    }

    /**
     * @return mixed
     */
    public function getResponse()
    {
        return $this->response;
    }

    /**
     * @param mixed $response
     */
    public function setResponse($response)
    {
        $response = preg_replace('/[\r\n]+/', '', $response);
        $this->response = dc_json_decode($response, true);
        $this->checkResponse($this->response);
    }

    /**
     * valid response
     * @param $response
     * @throws RequestException
     */
    protected function checkResponse($response) {}

    /**
     * @return mixed
     */
    public function getMethod()
    {
        return $this->method;
    }

    /**
     * @param mixed $method
     */
    public function setMethod($method)
    {
        $this->method = $method;
    }

    /**
     * @return mixed
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }

    /**
     * @param mixed $statusCode
     */
    public function setStatusCode($statusCode)
    {
        $this->statusCode = $statusCode;
    }

    /**
     * @return mixed
     */
    public function getMessage()
    {
        return $this->message;
    }

    /**
     * @param mixed $message
     */
    public function setMessage($message)
    {
        $this->message = $message;
    }

    /**
     * @return mixed
     */
    public function getApiMethodName()
    {
        return $this->apiMethodName;
    }
}